package com.myrpc.register.nacos;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.myrpc.autoconfig.MyRpcConfigEntity;
import com.myrpc.exception.MyRpcException;
import com.myrpc.loadBalance.LoadBalance;
import com.myrpc.loadBalance.implement.RandomLoadBalance;
import com.myrpc.register.ServiceDiscovery;
import com.myrpc.transfer.dto.RpcRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 实现Nacos的服务发现
 */
@Slf4j
@Component(value = "NacosServiceDiscovery")
@DependsOn({"MyRpcConfigEntity"})
public class NacosServiceDiscovery implements ServiceDiscovery {
    private String nacosAddress;
    private LoadBalance loadBalance;
    @Autowired
    public MyRpcConfigEntity myRpcConfig;

    public NacosServiceDiscovery(){
        //加载配置文件
//        InputStream stream = this.getClass().getClassLoader().getResourceAsStream("registerService.properties");
//        Properties properties = new Properties();
//        try {
//            properties.load(stream);
//        } catch (IOException e) {
//            log.error("加载注册中心的配置文件失败",e);
//            throw new RuntimeException(e);
//        }
        loadBalance = new RandomLoadBalance();
    }

    /**
     * 根据服务名称寻找服务地址
     *
     * @param rpcRequest 微服务名称
     * @return 服务地址
     */
    public InetSocketAddress discoveryService(RpcRequest rpcRequest) throws MyRpcException {
        //赋值配置中心地址
        this.nacosAddress = myRpcConfig.getNacosLocation();
        if (this.nacosAddress == null || this.nacosAddress.equals("")){
            throw new RuntimeException("配置中心地址非法");
        }
        List<Instance> allInstances = null;
        try {
            NamingService namingService = NamingFactory.createNamingService(this.nacosAddress);
            //得到该微服务全部的实例
            allInstances = namingService.getAllInstances(rpcRequest.getServiceName());
        }catch (NacosException exception){
            log.error("获得微服务实例失败");
            throw new MyRpcException(exception);
        }
        if (allInstances == null || allInstances.size() == 0){
            throw new MyRpcException("微服务实例列表为空");
        }
        //进行负载均衡 load balance
        Instance instance = loadBalance.selectService(allInstances, rpcRequest);
        //得到目标微服务的Rpc接受服务器端口
        Map<String, String> metadata = instance.getMetadata();
        String myRpcPort = metadata.get("my-rpc-port");
        if (myRpcPort == null || myRpcPort.equals("") || myRpcPort.trim().equals("")){
            throw new RuntimeException("目标微服务没有设置RPC请求接收端口或端口格式不正确");
        }
        InetSocketAddress address = new InetSocketAddress(instance.getIp(), Integer.parseInt(myRpcPort));
        log.info("The result after load balancing is {}", address);
        return address;
    }
}
